﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kpmg.CompanyInfo;

namespace MySearch
{
    
        #region profile and chargeable objects
        public enum CommonStatus { Active, Inactive }

        public enum CommonDataType { String, Datetime, Int32, Double }

        public enum CommonMemberRole { Member, Partner, Manager, Owner }

        public class CommonField
        {
            public string Name { get; private set; }
            public string Value { get; private set; }
            public CommonDataType DataType { get; private set; }

            public CommonField(string name, CommonDataType type, string value)
            {
                if (String.IsNullOrEmpty(name))
                    throw new Exception("CommonField.Constructor::Invalid name");

                this.Name = name;
                this.Value = String.IsNullOrEmpty(value) ? String.Empty : value;
                this.DataType = type;
            }
        }

        public class CommonMember
        {
            public string StaffNo { get; private set; }
            public CommonMemberRole Role { get; private set; }
            public bool IsSync { get; private set; }
            public CommonStatus Status { get; private set; }

            public Staff Staff
            {
                get
                {
                    if (!String.IsNullOrEmpty(StaffNo))
                        return StaffDAO.GetObject(StaffNo);
                    else
                        return null;
                }
                private set { }
            }

            public CommonMember(string staffNo, CommonMemberRole role, bool isSync, CommonStatus status)
            {
                this.StaffNo = staffNo;
                this.Role = role;
                this.IsSync = IsSync;
                this.Status = status;
            }
        }

        public enum ProfileType { Opportunity, ServiceTeam, Other }

        public enum ProfileStatus { Active, Inactive }

        public enum ProfileSource { PMS }

        public class FieldAndMemberBase : KpmgObject
        {
            public IDictionary<string, CommonField> Fields { get; private set; }
            public IDictionary<string, CommonMember> Members { get; private set; }

            public FieldAndMemberBase()
            {
                this.Fields = new Dictionary<string, CommonField>();
                this.Members = new Dictionary<string, CommonMember>();
            }

            public void AddField(string name, CommonDataType type, string value)
            {
                CommonField field = new CommonField(name, type, value);
                AddField(field);
            }

            public void AddField(CommonField field)
            {
                if (field == null)
                    throw new Exception("FieldAndMemberBase.AddField::Invalid object to add");

                if (this.Fields.ContainsKey(field.Name))
                    this.Fields[field.Name] = field;
                else
                    this.Fields.Add(field.Name, field);
            }

            public void AddMember(CommonMember member)
            {
                if (member == null || String.IsNullOrEmpty(member.StaffNo) || member.Staff == null)
                    return;// throw new Exception("FieldAndMemberBase.AddMemeber:Invalid staff no");

                if (this.Members.ContainsKey(member.StaffNo))
                    this.Members[member.StaffNo] = member;
                else
                    this.Members.Add(member.StaffNo, member);
            }
        }

        public class Profile : FieldAndMemberBase
        {
            public string ProfileCode { get; set; }
            public ProfileType ProfileType { get; set; }
            public string Description { get; set; }
            public ProfileStatus Status { get; set; }
            public ProfileSource Source { get; set; }
            private IList<Chargeable> chargeables;

            public IList<Chargeable> Chargeables
            {
                get
                {
                    if (chargeables == null)
                    {
                        chargeables = ChargeableOM.ListProfileChargeable(this.ProfileCode);
                        return chargeables;
                    }

                    return chargeables;
                }
            }


            public Profile() { }

            public override IDictionary<string, string> ToDictionary()
            {
                //IDictionary<string, string> dicRet = base.ToDictionary();
                IDictionary<string, string> dicRet = new Dictionary<string, string>();

                dicRet.Add("ProfileCode", this.ProfileCode);
                dicRet.Add("ProfileType", this.ProfileType.ToString());
                dicRet.Add("Description", this.Description);
                dicRet.Add("Status", this.Status.ToString());
                dicRet.Add("Source", this.Source.ToString());

                return dicRet;
            }
        }

        public enum ChargeableType { Engagement, InternalOrder, NA }

        public enum ChargeableSource { PMS }

        public enum ChargeableStatus { Active, Draft, Open, Frozen, Closed }

        public class Chargeable : FieldAndMemberBase
        {
            public string ChargeableCode { get; set; }
            public ChargeableType ChargeableType { get; set; }
            public string ProfileCode { get; set; }
            public string Description { get; set; }
            public bool IsMemberInherited { get; set; }
            public ChargeableStatus Status { get; set; }
            public ChargeableSource Source { get; set; }

            public override IDictionary<string, string> ToDictionary()
            {
                //IDictionary<string, string> dicRet = base.ToDictionary();
                IDictionary<string, string> dicRet = new Dictionary<string, string>();

                dicRet.Add("ChargeableCode", this.ChargeableCode);
                dicRet.Add("ChargeableType", this.ChargeableType.ToString());
                dicRet.Add("ProfileCode", this.ProfileCode);
                dicRet.Add("Description", this.Description);
                dicRet.Add("IsMemberInherited", this.IsMemberInherited.ToString());
                dicRet.Add("Status", this.Status.ToString());
                dicRet.Add("Source", this.Source.ToString());

                return dicRet;
            }
        }
        #endregion

        #region service template objects
        public enum ServiceStatus { Active, Inactive }

        public class ServiceCategory : KpmgObject
        {
            public string CategoryCode { get; private set; }
            public string Description { get; private set; }
            public ServiceStatus Status { get; private set; }

            public ServiceCategory(string code, string desc, ServiceStatus stat)
            {
                this.CategoryCode = code;
                this.Description = desc;
                this.Status = stat;
            }
        }

        public class ServiceType : KpmgObject
        {
            public string TypeCode { get; private set; }
            public string CategoryCode { get; private set; }
            public string Description { get; private set; }
            public ServiceStatus Status { get; private set; }

            public IList<int> Versions { get; private set; }
            public int CurrentVersion
            {
                get
                {
                    return this.Versions.Count == 0 ? -1 : this.Versions.Max();
                }
            }

            #region extended properties
            public ServiceCategory Category
            {
                get
                {
                    return null;// ServiceTemplateOM.GetServiceCategory(this.CategoryCode);
                }
            }
            #endregion

            #region overridable methods
            public override IDictionary<string, string> ToDictionary()
            {
                IDictionary<string, string> dicRet = base.ToDictionary();

                //Remove CurrentVersion, becuase it is extended property
                if (dicRet.ContainsKey("CurrentVersion"))
                    dicRet.Remove("CurrentVersion");

                return dicRet;
            }
            #endregion

            public ServiceType(string code, string catCode, string desc, ServiceStatus stat)
            {
                this.TypeCode = code;
                this.CategoryCode = catCode;
                this.Description = desc;
                this.Status = stat;
                this.Versions = new List<int>();
            }
        }

        public class ServiceStep : KpmgObject
        {
            public string TypeCode { get; private set; }
            public string StepCode { get; private set; }
            public string StepCodeUser { get; private set; }
            public string Description { get; private set; }

            public IList<int> Versions { get; private set; }
            public int CurrentVersion
            {
                get
                {
                    return this.Versions.Count == 0 ? -1 : this.Versions.Max();
                }
            }

            #region extended properties
            public ServiceType ServiceType
            {
                get
                {
                    return null;// String.IsNullOrEmpty(this.TypeCode) ? null : ServiceTemplateOM.GetServiceType(this.TypeCode);
                }
            }
            #endregion

            #region overridable methods
            public override IDictionary<string, string> ToDictionary()
            {
                IDictionary<string, string> dicRet = base.ToDictionary();

                //Remove CurrentVersion, becuase it is calculated property
                if (dicRet.ContainsKey("CurrentVersion"))
                    dicRet.Remove("CurrentVersion");

                return dicRet;
            }
            #endregion

            public ServiceStep(string stepCode, string typeCode, string usrCode, string desc)
            {
                this.StepCode = stepCode;
                this.TypeCode = typeCode;
                this.StepCodeUser = usrCode;
                this.Description = desc;

                this.Versions = new List<int>();
            }
        }

        public enum ServiceQuestionDataType { String, Int, UInt, Team, EngTeam, CheckBox, Choice, Office, File, List, Date, ConfirmTemplate, NA }

        public class ServiceQuestion : KpmgObject
        {
            public string QuesCode { get; set; }
            public string StepCode { get; set; }
            public string QuesCodeUser { get; set; }
            public string Nature { get; set; }
            public string Description { get; set; }
            public ServiceQuestionDataType DataType { get; set; }
            public bool IsMandatory { get; set; }
            public string ParentQuesCode { get; set; }
            public string ParentQuesAnswer { get; set; }

            public IList<int> Versions { get; private set; }
            public int CurrentVersion
            {
                get
                {
                    return this.Versions.Count == 0 ? -1 : this.Versions.Max();
                }
            }

            public IDictionary<string, string> Answers { get; private set; }

            #region overridable methods
            public override IDictionary<string, string> ToDictionary()
            {
                IDictionary<string, string> dicRet = base.ToDictionary();

                //Remove CurrentVersion, becuase it is calculated property
                if (dicRet.ContainsKey("CurrentVersion"))
                    dicRet.Remove("CurrentVersion");

                //Add answers
                if (this.Answers.Count > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (string strKey in this.Answers.Keys.OrderBy(x => x))
                    {
                        sb.Append(";" + this.Answers[strKey]);
                    }

                    dicRet.Add("Answers", "[" + sb.Remove(0, 1).ToString() + "]");
                }

                return dicRet;
            }

            public override IDictionary<string, string> FindDifference(KpmgObject objOld)
            {
                IDictionary<string, string> dicRet = base.FindDifference(objOld);

                //Ingore some properties
                IList<string> lstIgnore = new List<string> { "QuesCode", "StepCode" };
                foreach (string strKey in lstIgnore)
                {
                    if (dicRet.ContainsKey(strKey))
                        dicRet.Remove(strKey);
                }

                return dicRet;
            }
            #endregion

            #region extended properties
            public ServiceStep ServiceStep
            {
                get
                {
                    if (String.IsNullOrEmpty(this.StepCode))
                        return null;

                    return null;// ServiceTemplateOM.GetServiceStep(this.StepCode);

                }
            }
            #endregion

            public ServiceQuestion()
            {
                this.Versions = new List<int>();
                this.Answers = new Dictionary<string, string>();
            }
        }
        #endregion

        #region user and team related objects
        public enum UserRole { Requestor, Agent, Admin, SysAdmin }
        public enum TeamRole { Leader, Member }
        public enum TeamStatus { Active, Inactive }

        public class AgentTeam
        {
            public string Code { get; private set; }
            public string Name { get; private set; }
            public string Office { get; private set; }
            public bool IsSystem { get; private set; }
            public TeamStatus status { get; private set; }

            private IDictionary<string, TeamRole> _Members = null;
            public IDictionary<string, TeamRole> Members
            {
                get
                {
                    if (_Members != null)
                        return _Members;

                    _Members = UserInfoDAO.ListAgentTeamMember(this.Code);
                    return _Members;
                }
            }

            private IDictionary<Staff, TeamRole> _MemberStaffs = null;
            public IDictionary<Staff, TeamRole> MemberStaffs
            {
                get
                {
                    if (_MemberStaffs != null)
                        return _MemberStaffs;

                    IDictionary<Staff, TeamRole> dicRet = new Dictionary<Staff, TeamRole>();
                    foreach (KeyValuePair<string, TeamRole> keyPair in Members)
                    {
                        Staff staff = StaffDAO.GetObject(keyPair.Key);
                        if (staff != null && !dicRet.ContainsKey(staff))
                            dicRet.Add(staff, keyPair.Value);
                    }

                    _MemberStaffs = dicRet;
                    return _MemberStaffs;
                }
            }

            private IList<string> _ServiceTypeCodes = null;
            public IList<string> ServiceTypeCodes
            {
                get
                {
                    if (_ServiceTypeCodes != null)
                        return _ServiceTypeCodes;

                    _ServiceTypeCodes = UserInfoDAO.ListAgentTeamServiceType(this.Code);
                    return _ServiceTypeCodes;
                }
            }

            private IList<ServiceType> _ServiceTypes = null;
            public IList<ServiceType> ServiceTypes
            {
                get
                {
                    if (_ServiceTypes != null)
                        return _ServiceTypes;
                    return null;

                    //IList<ServiceType> lstRet = new List<ServiceType>();
                    //foreach (string strTemp in ServiceTypeCodes)
                    //    lstRet.Add(ServiceTemplateOM.GetServiceType(strTemp));

                    //_ServiceTypes = lstRet;
                    //return _ServiceTypes;
                }
            }

            public AgentTeam(string code, string name, string office, bool isSystem, TeamStatus status)
            {
                this.Code = code;
                this.Name = name;
                this.Office = office;
                this.status = status;
                this.IsSystem = isSystem;
            }
        }

        public class UserInfo
        {
            public Staff Staff { get; private set; }
            public UserRole Role { get; private set; }
            public IList<string> TeamCodes { get; private set; }

            internal UserInfo() { }

            internal UserInfo(Staff staff, UserRole role, IList<string> teamCodes)
            {
                this.Staff = staff;
                this.Role = role;
                this.TeamCodes = teamCodes;
            }
        }
        #endregion

        #region Tikcet related objects
        public enum CostUnit { Hour025, Hour050, Hour100 }

        public enum TicketStatus { Assigned, Closed, Completed, Confirmed, DataNeeded, Draft, Hold, Open, Rejected, Returned, Rework, WithDrawn }

        public enum QuestionType { Template, Common }

        public class Ticket : KpmgObject
        {
            public string TicketNo { get; set; }
            public string ProfileCode { get; set; }
            public string ChargeableCode { get; set; }
            public string TypeCode { get; set; }
            public int VerNo { get; set; }
            public string ChargeableCostCentreNo { get; set; }
            public string RequestorStaffNo { get; set; }
            public string RequestorCostCentreNo { get; set; }
            public string AssignedTeamCode { get; set; }
            public string AssignedStaffNo { get; set; }
            public string PickupStaffNo { get; set; }
            public CostUnit CostUnit { get; set; }
            public double CostEstimated { get; set; }
            public double CostActual { get; set; }
            public TicketStatus Status { get; set; }
            public string ActiveDialogueID { get; set; }
            public DateTime CreatedTime { get; set; }
            public string CreatedUserID { get; set; }
            public DateTime UpdatedTime { get; set; }
            public string UpdatedUserID { get; set; }

            public Ticket() { }
        }

        public class TicketStep : KpmgObject
        {
            public string TicketNo { get; set; }
            public string StepCode { get; set; }
            public string Status { get; set; }
            public double CostEstimated { get; set; }
            public double CostActual { get; set; }
            public string Remarks { get; set; }
            public DateTime UpdatedTime { get; set; }
            public string UpdateUserID { get; set; }

            public TicketStep() { }
        }

        public class TicketData : KpmgObject
        {
            public string TicketNo { get; set; }
            public string QuesCode { get; set; }
            public string StepCode { get; set; }
            public QuestionType QuesType { get; set; }
            public string Answer { get; set; }
            public DateTime UpdatedTime { get; set; }
            public string UpdatedUser { get; set; }

            public TicketData() { }
        }

        #endregion

        #region Ref data objects

        public class ConfirmTemplate
        {
            public string ConfirmID { get; private set; }
            public string ConfirmName { get; private set; }
            public string ExcelTemplateUrl { get; private set; }

            public ConfirmTemplate(string confirmID, string confirmName, string excelTemplateUrl)
            {
                this.ConfirmID = confirmID;
                this.ConfirmName = confirmName;
                //this.ExcelTemplateUrl = AppConfigurer.ConfirmTemplateUrl + excelTemplateUrl;
            }
        }

        public class ConfirmInfo
        {
            public string TicketNo { get; set; }
            public string LetterID { get; set; }
            public string StatusDesc { get; set; }
            public string ConfirmName { get; set; }
            public string EntityName { get; set; }
            public string ReceiverName { get; set; }
            public DateTime AuditDate { get; set; }
            public DateTime DateSendToAddressee { get; set; }
            public string CourierNumber { get; set; }
            public string Remark { get; set; }

            public ConfirmInfo() { }
        }

        #endregion
    
}
